/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package airacrobats.game;

import airacrobats.game.object.Airplane;
import airacrobats.io.data.JWavefrontModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.vecmath.Point3f;

/**
 * This class controls the smoke of an airplane.
 */
public class Smoker
{
    /**
     * Amount of particles of the smoke.
     */
    private final static int COUNT = 900;

    /**
     * The smoke model.
     */
    private JWavefrontModel model;
    /**
     * Smoke particles.
     */
    private List<Smoke> smokes;
    /**
     * The airplane.
     */
    private Airplane airplane;
    /**
     * Random object.
     */
    private Random random;
    /**
     * Next smoke index.
     */
    private int nextSmoke;
    /**
     * Elapsed time since the last smoke.
     */
    private long time;
    /**
     * The time elapsed to create another smoke.
     */
    private long nextSmokeTime;

    /**
     * @param smokeModel The smoke model.
     * @param airplane The airplane.
     */
    public Smoker(JWavefrontModel smokeModel, Airplane airplane)
    {
        this.model = smokeModel;
        this.airplane = airplane;
        smokes = new ArrayList<Smoke>();
        for (int i = 0; i < COUNT; ++i)
            smokes.add(new Smoke());
        random = new Random();
    }

    /**
     * @return The model.
     */
    public JWavefrontModel getModel()
    {
        return model;
    }

    /**
     * Updates the smokes and create more particles of it.
     * @param autoDrawable The auto drawable context.
     * @param deltaTime The delta time.
     */
    public void updateAndDraw(GLAutoDrawable autoDrawable, long deltaTime)
    {
        time += deltaTime;

        if (!airplane.isSmokeOn())
        {
            time = 0;
        }
        else if (time > nextSmokeTime)
        {
            long particlesCount = 1;
            if (nextSmokeTime > 0)
                particlesCount = time / nextSmokeTime;

            time -= particlesCount * nextSmokeTime;

            nextSmokeTime = 18000000L - random.nextInt(1000000);

            for (int i = 0; i < particlesCount; ++i)
            {
                Point3f smokePosition = new Point3f(
                        0.6f - random.nextFloat() * (i + 1) * 0.5f, -0.01f, 0.1f);
                airplane.getRMatrixInverse().transform(smokePosition);
                smokePosition.add(airplane.getPosition());

                smokes.get(nextSmoke).position = new Point3f(airplane.getPosition());
                smokes.get(nextSmoke).scale = (random.nextInt(100) * 0.005f) * Smoke.SIZE;
                smokes.get(nextSmoke).scaleX = smokes.get(nextSmoke).scale;
                smokes.get(nextSmoke).time = 0;
                smokes.get(nextSmoke).alpha = 0.85f;
                smokes.get(nextSmoke++).position = smokePosition;

                nextSmoke = nextSmoke % COUNT;
            }
        }

        GL2 gl = autoDrawable.getGL().getGL2();

        float scaleAdd = 0.5f * deltaTime / 1000000000.0f;

        gl.glDisable(GL2.GL_LIGHTING);

        for (int i = 0; i < COUNT; ++i)
        {
            if (smokes.get(i).position == null)
                continue;

            Smoke smoke = smokes.get(i);

            smoke.scaleX += scaleAdd;
            smoke.scale += scaleAdd;
            smoke.time += deltaTime;
            smoke.scaleX = smokes.get(i).scaleX > 2.5f ? 2.5f : smokes.get(i).scaleX;
            smoke.scale = smokes.get(i).scale > 1.5f ? 1.5f : smokes.get(i).scale;

            if (smoke.time > Smoke.FADE_TIME)
            {
                smoke.alpha += 0.01f * deltaTime / 1000000000.0f;
                if (smoke.alpha > 1.0f)
                    smoke.alpha = 1.0f;
            }
            
            if (smoke.time > Smoke.TIME)
            {
                smoke.position = null;
                continue;
            }

            gl.glPushMatrix();

            gl.glTranslatef(smoke.position.x, smoke.position.y, smoke.position.z);

            gl.glScalef(smoke.scaleX, smoke.scale, smoke.scale);

            gl.glColor4f(0.7f, 0.7f, 0.7f, smoke.alpha);

            model.draw(autoDrawable);

            gl.glPopMatrix();
        }

        gl.glEnable(GL2.GL_LIGHTING);
    }

    /**
     * Smoke class.
     */
    class Smoke
    {
        /**
         * Average size of the smoke.
         */
        final static float SIZE = 0.5f;
        /**
         * Time to live of the smoke.
         */
        final static long TIME = 15000000000L;
        /**
         * Time when the smoke starts to fade.
         */
        final static long FADE_TIME = 1000000000L;
        /**
         * Time lived of the smoke.
         */
        long time;
        /**
         * Scale y-z axis.
         */
        float scale;
        /**
         * Scale x axis.
         */
        float scaleX;
        /**
         * Visibility.
         */
        float alpha;
        /**
         * Position.
         */
        Point3f position;
    }
}

